#ifndef __HELPER_H__
#define __HELPER_H__

#include "temu.h"
#include "operand.h"

#define FUNC_MASK 0x0000003F
#define RS_MASK 0x03E00000
#define RT_MASK 0x001F0000
#define RD_MASK 0x0000F800
#define SA_MASK 0x000007C0

#define SHAMT_MASK 0x000007C0
#define IMM_MASK 0x0000FFFF
#define INDEX_MASK 0x03FFFFFF
#define HIGH_IMM_MASK 0xFFFF0000

#define OPCODE_SIZE 6
#define FUNC_SIZE 6
#define RS_SIZE 5
#define RT_SIZE 5
#define RD_SIZE 5
#define SHAMT_SIZE 5
#define IMM_SIZE 16
#define INDEX_SIZE 26

#define REG_NAME(index) regfile[index]

/* All function defined with 'make_helper' return the length of the operation. */
#define make_helper(name) void name(uint32_t pc)

static inline uint32_t instr_fetch(uint32_t addr, size_t len) {
	return mem_read(addr, len);
}

static inline void exception(int type_e , uint32_t err_addr){
	if(cpu.my_status.exl){
		if(type_e == Int)
		return;
		else{
			cpu.my_cause.ExcCode = type_e;
			if (type_e == AdEL || type_e == AdES){
				cpu.err_vaddr = err_addr;
				//record
			}
			cpu.pc = 0xbfc00380 - 4;
			//refresh pc
		}
	}else{
		if(type_e == AdEL || type_e == AdES){
			cpu.err_vaddr = err_addr;
		}
		cpu.my_cause.ExcCode = type_e;

		
		cpu.my_status.exl = 1;
		
		cpu.epc = cpu.pc;

		cpu.pc =0xbfc00380 - 4;
	}

	//todo:modify
	switch (type_e)
	{
		case Int:     fprintf(stderr, "int中断\n");break;
		case AdEL:    fprintf(stderr, "读地址错误\n");break;
		case AdES:    fprintf(stderr, "写地址错误\n");break;
		case Sys:     fprintf(stderr, "系统调用\n");break;
		case Bp:      fprintf(stderr, "断点\n");break;
		case RI:      fprintf(stderr, "保留指令\n");break;
		case Ov:      fprintf(stderr, "溢出\n");break;
	}
}



/* shared by all helper function */
extern Operands ops_decoded;

#define op_src1 (&ops_decoded.src1)
#define op_src2 (&ops_decoded.src2)
#define op_dest (&ops_decoded.dest)

#ifdef DEBUG
#define print_asm(...) Assert(snprintf(assembly, 80, __VA_ARGS__) < 80, "buffer overflow!")
#else
#define print_asm(...)
#endif


#endif
